package main

import (
	"fmt"
	"github.com/xuri/excelize/v2"
	"gopkg.in/yaml.v3"
	"io/ioutil"
	"strconv"
	"time"
)

/*
时间常量
*/
const (
	SecondsPerMinute = 60
	SecondsPerHour = SecondsPerMinute * 60
	SecondsPerDay = SecondsPerHour * 24
)

type Resource struct {
	Config	struct{
		LoginUrl	string
		Username	string
		Password	string
	}
	OutDirConf	[]Group
}
type Group	struct{
	GroupName string
	Path	string
}

func RevTime(str string) string {
	i, _ := strconv.ParseInt(str, 10, 64)
	timeFormat := "2006-01-02 15:04:05"
	Loc, _ := time.LoadLocation("Asia/Shanghai")
	t:=time.Unix(i, 0).In(Loc)
	return t.Format(timeFormat)+" 🔄"
}

type hostInfo struct {
	GroupID,  hostName, ip, SN string
	string
}

type hostItem struct {
	uptime					string	//系统运行时间
	cpuNum					string	//cpuNUM
	min1, min5, min15 		string	//cpu负载信息
	hostname, hostIP		string	//主机名称，主机信息
	memTotal				string	//内存总量
	memAvailable			string  //可用内存
	memUsed					string	//内存使用率
	cpuUsed					string	//CPU使用率
	diskRootSize			string  //根目录大小
	diskRootused			string	//根目录使用情况
	diskData1Size			string
	diskData1used			string
	DAU, DAT,DU, DT, MEMA, MEMT		int64	//磁盘，内存计算
	diskRoot				string	//根目录磁盘使用率
	diskData1				string
	version					string
	isOk					bool
	SN						string
	HostRestartCount		int		//主机重启次数
	clock  					string		//发生时间
}
type ItemRst struct {
	Result []struct {
		Key string `json:"key_"`
		HostID string	`json:"hostid"`
		Lastvalue string `json:"lastvalue"`
		Itemid   string `json:"itemid"`
	} `json:"result"`
}
//读取yaml配置文件函数
func ReadYaml(FileName *Resource) error {
	yamlFile, err := ioutil.ReadFile("./zbx.yml")
	if err != nil {
		fmt.Printf("读取yml配置文件失败,详细原因-> : %v\n", err)
		return err
	}
	err = yaml.Unmarshal(yamlFile, FileName)
	if err != nil {
		fmt.Printf("yml文件解析失败, 详细原因-> : %v\n", err)
		return err
	}
	return nil
}

/*
时间转换函数
*/
func resolveTime(seconds float64) (day float64) {return seconds / SecondsPerDay}

// 磁盘字节的单位转换 保留两位小数
func formatFileSize(fileSize int64) (size string) {
	if fileSize < 1024 {
		//return strconv.FormatInt(fileSize, 10) + "B"
		return fmt.Sprintf("%.2f B", float64(fileSize)/float64(1))
	} else if fileSize < (1024 * 1024) {
		return fmt.Sprintf("%.2f KB", float64(fileSize)/float64(1024))
	} else if fileSize < (1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f MB", float64(fileSize)/float64(1024*1024))
	} else if fileSize < (1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f GB", float64(fileSize)/float64(1024*1024*1024))
	} else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f TB", float64(fileSize)/float64(1024*1024*1024*1024))
	} else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
		return fmt.Sprintf("%.2f EB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
	}
}
//流量单位计算
func formatFileSize1(fileSize int64) (size string) {
	if fileSize < 1024 {
		//return strconv.FormatInt(fileSize, 10) + "B"
		return fmt.Sprintf("%.2f Bbps", float64(fileSize)/float64(1))
	} else if fileSize < (1024 * 1024) {
		return fmt.Sprintf("%.2f Kbps", float64(fileSize)/float64(1024))
	} else if fileSize < (1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f Mbps", float64(fileSize)/float64(1024*1024))
	} else if fileSize < (1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f Gbps", float64(fileSize)/float64(1024*1024*1024))
	} else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f Tbps", float64(fileSize)/float64(1024*1024*1024*1024))
	} else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
		return fmt.Sprintf("%.2f Ebps", float64(fileSize)/float64(1024*1024*1024*1024*1024))
	}
}

//希尔排序
func shellSort(arr *[]*hostItem) {
	lenght := len(*arr)
	for gap := lenght>>1; gap > 0; gap = gap>>1 {
		for i := gap; i< lenght; i++ {
			tmp, a := (*arr)[i], i-gap
			for ; a>0 && tmp.hostname < (*arr)[a].hostname; a -= gap {
				(*arr)[a+gap] = (*arr)[a]
			}
			(*arr)[a+gap]=tmp
		}
	}
}


func CreateExcelFile(path, groupName string, itemInfo *map[string]*hostItem){
	file := excelize.NewFile()
	arrRow :=[]string{"","A", "B", "C", "D", "E", "F", "G", "H"}
	err := file.SetSheetRow("Sheet1", "A1", &[]interface{}{
		"主机名",
		"SN",
		"版本信息",
		"运行时长/天",
		"重启次数/一周内",
		"内存总量 /空闲 /使用率",
		"CPU使用率",
		"根目录容量/使用率",
	})
	if err != nil {fmt.Println(err); return}
	style, _ := file.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical: "",
		},
		Fill: excelize.Fill{Type: "pattern", Color: []string{"#E0EBF5"}, Pattern: 1},
	})
	stopStyle, _ := file.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical: "",
		},
		Fill: excelize.Fill{Type: "pattern", Color: []string{"#FF9900"}, Pattern: 1},
	})
	for i:=1; i< 9; i++ {A := fmt.Sprintf("%s1", arrRow[i]); file.SetCellStyle("Sheet1", A, A, style)}
	style1, _ := 	file.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical: "",
		},
	})
	sortArr := []*hostItem{}
	for hostid, ve := range *itemInfo {
		sortArr = append(sortArr, ve)
		delete(*itemInfo, hostid)
	}
	shellSort(&sortArr)
	i := 2
	for _, ve := range sortArr {
		A := fmt.Sprintf("A%d", i)
		file.SetSheetRow("Sheet1", A, &[]interface{}{
			ve.hostname,
			ve.SN,
			ve.version,
			ve.uptime,
			ve.HostRestartCount,
			fmt.Sprintf("%s /%s /%s", ve.memTotal, ve.memAvailable, ve.memUsed),
			ve.cpuUsed,
			fmt.Sprintf("%s /%s", ve.diskRootSize, ve.diskRoot),
		})
		if ve.HostRestartCount != 0 {
			D := fmt.Sprintf("E%d", i)
			text := fmt.Sprintf(`{"author":"共重启了-> ","text":"%d次\n%s"}`, ve.HostRestartCount, ve.clock)
			if ve.isOk {
				text = fmt.Sprintf(`{"author":"共重启了-> ","text":"%d次\n%s\n当前设备处于离线状态 -> 😑"}`, ve.HostRestartCount, ve.clock)
			}
			file.AddComment("Sheet1", D, text)
		}
		for j:=1; j < 9; j++{
			B := fmt.Sprintf("%s%d",arrRow[j], i)
			if ve.isOk {
				file.SetCellStyle("Sheet1", B, B, stopStyle)
				continue
			}
			file.SetCellStyle("Sheet1", B, B, style1)
		}
		i++
	}
	if err = file.SaveAs(path+"\\"+groupName+".xlsx"); err != nil {
		fmt.Println(err)
	}
	file.Close()
}